﻿using System;
using System.Collections.Generic;
using Cellbi.SvZLib;
using Shine.Util.Security;

namespace Shine.Util.Serialization
{
    /// <summary>
    /// 安全序列化
    /// </summary>
    public static class SecuritySerialization
    {
        /// <summary>
        /// 加密一个对象后序列化到文本。
        /// </summary>
        /// <param name="obj">需要进行加密的对象。</param>
        /// <returns>加密得到的文本。</returns>
        public static string Encrypt(object obj)
        {
            return Encrypt(obj, null);
        }

        /// <summary>
        /// 加密一个对象后序列化到文本。
        /// </summary>
        /// <param name="obj">需要进行加密的对象。</param>
        /// <param name="knownTypes">可在对象图中呈现的已知类型的集合。</param>
        /// <returns>加密得到的文本。</returns>
        public static string Encrypt(object obj, IEnumerable<Type> knownTypes)
        {
            if (obj == null)
            {
                return null;
            }

            byte[] bytes = DataContractSerialization.Serialize(obj, knownTypes);
            bytes = Utils.Compress(bytes);
            return AesCryptography.Encrypt(bytes);
        }

        /// <summary>
        /// 解密文本后反序列化到一个对象。
        /// </summary>
        /// <typeparam name="T">该对象的类型。</typeparam>
        /// <param name="encryptedString">待解密的文本。</param>
        /// <returns>解密文本得到的对象。</returns>
        public static object Decrypt<T>(string encryptedString)
        {
            return Decrypt<T>(encryptedString, null);
        }

        /// <summary>
        /// 解密文本后反序列化到一个对象。
        /// </summary>
        /// <typeparam name="T">该对象的类型。</typeparam>
        /// <param name="encryptedString">待解密的文本。</param>
        /// <param name="knownTypes">可在对象图中呈现的已知类型的集合。</param>
        /// <returns>解密文本得到的对象。</returns>
        public static object Decrypt<T>(string encryptedString, IEnumerable<Type> knownTypes)
        {
            if (string.IsNullOrEmpty(encryptedString))
            {
                return null;
            }

            byte[] bytes = AesCryptography.Decrypt(encryptedString);
            bytes = Utils.Decompress(bytes);
            return DataContractSerialization.Deserialize<T>(bytes, knownTypes);
        }
    }
}
